﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Configuration;
using System.Configuration;
using System.ComponentModel;

namespace YasharEl.Infrastructure.ServiceModel.Messaging
{
    public class MessageHeaderAttacherBehaviourExtensionElement : BehaviorExtensionElement
    {
        internal const string MessageHeadersPropertyName = "messageHeaders";

        [ConfigurationProperty(MessageHeadersPropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)]
        public MessageHeaderProvidersCollection MessageHeaders
        {
            get
            {
                return (MessageHeaderProvidersCollection)base[MessageHeadersPropertyName];
            }
            set
            {
                base[MessageHeadersPropertyName] = value;
            }
        }

        public override Type BehaviorType
        {
            get { return typeof(MessageHeaderInformationAttacher); }
        }

        protected override object CreateBehavior()
        {
            List<MessageHeaderProviderInformation>  messageHeaderEntries = new List<MessageHeaderProviderInformation>();

            foreach (MessageHeaderProviderConfig messageHeaderProviderConfig in MessageHeaders)
            {
                IMessageHeaderValueProvider valueProvider = null;
                try
                {
                    valueProvider = Activator.CreateInstance(messageHeaderProviderConfig.ValueProviderType) as IMessageHeaderValueProvider;
                }
                catch (Exception e)
                {
                    throw new InvalidSystemConfigurationException(
                        string.Format("Invalid value provider type of {0} message header config.", messageHeaderProviderConfig.Key),
                        e
                    );
                }

                if( valueProvider == null )
                {
                    throw new InvalidSystemConfigurationException(
                        string.Format("Invalid value provider type of {0} message header config.", messageHeaderProviderConfig.Key)
                    );
                }

                messageHeaderEntries.Add(
                    new MessageHeaderProviderInformation(
                        messageHeaderProviderConfig.Key,
                        messageHeaderProviderConfig.Namespace,
                        valueProvider
                    )
                );

            }

            return new MessageHeaderInformationAttacher(messageHeaderEntries);
        }
    }

    public class MessageHeaderProvidersCollection : ConfigurationElementCollection
    {
        internal const string messageHeaderProviderConfigPropertyName = "messageHeaderProvider";

        public override ConfigurationElementCollectionType CollectionType
        {
            get
            {
                return ConfigurationElementCollectionType.BasicMapAlternate;
            }
        }

        protected override string ElementName
        {
            get
            {
                return messageHeaderProviderConfigPropertyName;
            }
        }

        protected override bool IsElementName(string elementName)
        {
            return messageHeaderProviderConfigPropertyName == elementName;
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new MessageHeaderProviderConfig();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((MessageHeaderProviderConfig)(element)).Key;
        }
    }

    public class MessageHeaderProviderConfig : ConfigurationElement
    {
        internal const string KeyPropertyName = "key";
        internal const string NamespacePropertyName = "namespace";
        internal const string ValueProviderTypePropertyName = "valueProviderType";

        [ConfigurationPropertyAttribute(KeyPropertyName, IsRequired = true, IsKey = true, IsDefaultCollection = false)]
        public string Key
        {
            get
            {
                return ((string)(base[MessageHeaderProviderConfig.KeyPropertyName]));
            }
            set
            {
                base[MessageHeaderProviderConfig.KeyPropertyName] = value;
            }
        }

        [ConfigurationPropertyAttribute(NamespacePropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)]
        public string Namespace
        {
            get
            {
                return ((string)(base[MessageHeaderProviderConfig.NamespacePropertyName]));
            }
            set
            {
                base[MessageHeaderProviderConfig.NamespacePropertyName] = value;
            }
        }

        [TypeConverter(typeof(TypeNameConverter))]
        [ConfigurationPropertyAttribute(ValueProviderTypePropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)]
        public Type ValueProviderType
        {
            get
            {
                return ((Type)(base[ValueProviderTypePropertyName]));
            }
            set
            {
                base[ValueProviderTypePropertyName] = value;
            }
        }
    }
}
